#include "fsyntax.hpp"
#include "ftool.hpp"

fairy::Fsyntax::Fsyntax() {
    //从配置文件读取出的每一行
    std::string produceStr;
    //产生式中单词
    std::string str;

    //加载配置文件
    if(!fairy.open("conf/syntax.conf",Ffile::in|Ffile::binary))
    {
        fcout("不能打开语法配置文件")
        return;
    }

    while(!fairy.get_value().eof())
    {
        //每行中的第几个字符，分析产生式必不可少的部分
        int times = 0;
        Produce tempProduce; 

        //配置文件中，每一行为一个产生式，以#开头的行为注释
        produceStr = fairy.read_line();
        std::istringstream produce(produceStr);
        //分析产生式
        while(!produce.eof()) {
            produce >> str;
            //如果是第一个字符，则定义为起始符
            if(times == 0)
                tempProduce.origin = str;
            //如果times>0，则依次将后续添加到array中
            else 
            {
                tempProduce.array[times-1] = str;
                tempProduce.length++;
            }
            //就是++呗
            ++times;
        }
        //产生式后续的长度
        tempProduce.length = times;
        //将这个产生式添加到文法池中
        this->grammerPool.push_back(tempProduce);
    }
    //初始化终结符和非终结符集合
    make_terminator();
    make_non_terminator();


    //初始化first集合
    make_first();
}

fairy::Fsyntax::~Fsyntax(){
    //如果fairy被创建并绑定文件，则释放这个文件描述符
    if(fairy.get_value().is_open())
        fairy.close();
};
/*
 *  构造终结符集合
 *  方法：
 *      所有的终结符无法继续向下扩展，非终结符必须要向下扩展
 *      所以，就上下文无关的文法来说，所有产生式的起始符，都是非终结符
 *      而产生式右面的，出去所有的非终结符，就是所有的终结符
 */
auto fairy::Fsyntax::make_terminator() -> void
{
    GP::iterator first = grammerPool.begin();

    for(GP::iterator iter = first; iter != grammerPool.end(); iter++)
    {
        fdebug(iter->origin, 8.8)
        nonTerminators.insert(iter->origin);
    }
}
//够着非终结符集合
auto fairy::Fsyntax::make_non_terminator() -> void{
    GP::iterator first = grammerPool.begin();

    for(GP::iterator iter = first; iter != grammerPool.end(); iter++)
    {
        for(int i = 0; i < PRODUCE_MAX_SIZE; i++) {
            if(!nonTerminators.count(iter->array[i]))
                terminators.insert(iter->array[i]);
        }   
        nonTerminators.erase("");
    }

}

/*
 *  递归，向下查找，知道找到第一个终结符
 *  从文法的起始符开始，取出语句中的第一个单词
 *      如果单词是终结符，则不向下递归
 *      如果是非终结符，则：    
 *      将非终结符的层级+1，将该非终结符层级结构压入栈顶。
 *      在递归返回时，如果被递归（x）的非终结符层级大于这一层(A)的，则将First(x)中所有的终结符存入First（A)中
 *      这里在集合传递时，没有考虑将空集合排除，因为储存first的集合用的是set容器，会自动过滤掉重复的
 * 
 *      函数返回的int值是非终结符递归的层级
 */
auto fairy::Fsyntax::find_terminator(std::string terStr,int leave) -> int 
{
    //初始化层级结构
    NonTerminatorLeave nl;
    nl.str = terStr;
    nl.leave = leave;
    nonTerminatorStack.push(nl);
    std::vector<Produce>::iterator first = grammerPool.begin();
    //遍历文法池，一个一个判断
    for(std::vector<Produce>::iterator iter = first; iter != grammerPool.end(); iter++)
    {
        //在文法池中找到由这个起始符所在的产生式
        if(iter->origin == terStr) {
            //如果产生式右面第一个为终结符，则将终结符添加到First[x]中
            if(is_terminator(iter->array[0])) {
                this->First[terStr].insert(iter->array[0]);
            }
            //如果不是，继续递归
            else{
                //如果递归返回的层级高于当前层级，则递归函数中的First集合拷贝到当前层级的First集合中
                if(leave < find_terminator(iter->array[0], nl.leave + 1))
                {
                    //拷贝
                    CP_FIRST_MAP(iter->origin, iter->array[0])
                    //栈顶元素出栈
                    nonTerminatorStack.pop();
                }
            }
        }
    }
    //将本层级别返回
    return leave;
}

auto fairy::Fsyntax::make_first() ->void {

    std::set<std::string>::iterator begin = nonTerminators.begin();

    //判断一个First集合中有没有空符
    auto have_null = [&](std::string value){return First[value].count(NULL_WORD) ? true : false;};
    //在不考虑空符号的前提下，创建所有非终结符的First集合
    for(std::set<std::string>::iterator iter = begin; iter != nonTerminators.end();++iter)
    {
        //如果First的非终结符中没有改非终结符的键（说明该终结符还没创建First集合），就递归它
        if(!First.count(*iter))
            this->find_terminator(*iter,0);
    }

    //vscode这里会报个智障错误
    std::vector<Produce>::iterator begin1 = grammerPool.begin();

    for(std::vector<Produce>::iterator _iter = begin1; _iter != grammerPool.end(); ++_iter)
    {
        fdebug(std::string("轮到"+_iter->origin+"检测啦"),1.1)
        for(int i = 0; i < PRODUCE_MAX_SIZE; i++)
        {
            std::string str1 = _iter->origin;
            std::string str2 = _iter->array[i+1];
            //如果遍历到终结符，将终结符添加进First(_iter->origin)中就可以了
            //如果是非终结符直接跳过这个向下循环就好了
            if(is_terminator(_iter->array[i])) break;
            if(have_null(_iter->array[i])) break;
            if(i == _iter->length)
            {
                First[_iter->origin].insert(NULL_WORD);
                break;
            }
            fdebug(std::string("将"+str2+"拷贝进"+str1), 2.2)
            CP_FIRST_MAP(str1, str2)
        }            
    }
    
}

auto fairy::Fsyntax::make_follow() ->void {

}

auto fairy::Fsyntax::display_first() -> void
{
    FirstMap::iterator temp = this->First.begin();

    std::cout << "-------first集合------" << std::endl;
    for(FirstMap::iterator iter = temp; iter != First.end(); iter++)
    {
        std::cout << iter->first << std::endl; 
        for(std::set<std::string>::iterator iter1 = iter->second.begin();
            iter1 != iter->second.end(); iter1++){
                std::cout << *iter1 << std::flush;
        }
        std::cout << std::endl;

    }
}
//输出所有的终结符
auto fairy::Fsyntax::display_terminator() -> void
{
    std::set<std::string>::iterator first = terminators.begin();
    
    std::cout << "--------终结符都有--------" << std::endl;
    for(std::set<std::string>::iterator iter = first; iter != terminators.end(); iter++)
    {
        std::cout << *iter << std::endl;
    }
}

//输出所有的非终结符
auto fairy::Fsyntax::display_non_terminator() -> void
{
    std::set<std::string>::iterator first = nonTerminators.begin();
    
    std::cout << "--------非终结符都有--------" << std::endl;
    for(std::set<std::string>::iterator iter = first; iter != nonTerminators.end(); iter++)
    {
        std::cout << *iter << std::endl;
    }
}

//输出所有的产生式
auto fairy::Fsyntax::display_grammer() -> void
{
    GP::iterator first = grammerPool.begin();
    for(GP::iterator iter = first; iter != grammerPool.end(); iter++)
    {
        std::cout << iter->origin << " -> " << std::flush;
        for(int i = 0; i < PRODUCE_MAX_SIZE; ++i)
        {
            std::cout << iter->array[i] << " " << std::flush;
        }
        std::cout << std::endl;
    } 
}
